<template>
  <slot>
    <el-button link type="primary" icon="Top" @click="handleOpen">{{
      btnName
    }}</el-button>
  </slot>
  <basic-dialog v-model="visible" :title="title" :width="width" :autoClose="false" :submitBtnLoading="submitBtnLoading"
    :aytoClose="false" :hideFooter="true">
    <div class="up_header">
      <OtherAttr v-if="isAttrShow" v-model="formData" :secretList="secretList"
        :fileDocClassifyList="fileDocClassifyList"></OtherAttr>
      <el-upload v-model="fileList" v-bind="attrs" :drag="drag" :class="{ drag }" :action="action"
        :show-file-list="false" :headers="{
          ...headers,
          'h-authorization-token': token,
        }" :data="{
          ...formData,
          ownId: curRowDataKeyVal,
          ownBus: curRowDataBusVal,
          ...data,
        }" :before-upload="handleBeforeUpload" :on-change="handlleUpChange" :on-progress="handleProgress">
        <slot>
          <el-button type="primary" icon="upload-filled">附件上传</el-button>
        </slot>
      </el-upload>
    </div>
    <div class="file_table_table">
      附件列表 <span class="tip">{{ tipShow }}</span>
    </div>
    <div class="mb_10">
      <el-button v-if="isAttrShow" :disabled="selectedlist.length === 0" type="primary" icon="Edit"
        @click="handleOpenEditAttrDialog">批量编辑附件属性</el-button>
      <el-button :disabled="selectedlist.length === 0" type="danger" icon="Delete" @click="handleDel()">批量删除</el-button>
    </div>
    <el-table :data="fileList" border style="width: 100%" max-height="50vh" v-loading="tableLoading"
      @selection-change="handleSelectChange">
      <el-table-column type="selection" width="55" align="center" />
      <el-table-column type="index" label="序号" width="80" align="center"></el-table-column>
      <el-table-column prop="name" label="附件名称" min-width="250">
        <template #default="{ row }">
          <span>{{ row.showName || row.name }}</span>
        </template>
      </el-table-column>
      <el-table-column prop="secret" label="密级" min-width="80" align="center" v-if="secretList.length > 0">
        <template #default="{ row }">{{
          secretList.find((item) => item.value === row.secret)?.label
        }}</template>
      </el-table-column>
      <el-table-column v-if="fileDocClassifyList.length > 0" prop="fileDocClassifyName" label="附件用途" min-width="120"
        align="center">
      </el-table-column>
      <el-table-column prop="createTime" label="首次上传时间" min-width="160" align="center"></el-table-column>
      <el-table-column prop="modifyTime" label="最后更改时间" min-width="160" align="center"></el-table-column>
      <el-table-column prop="fileExtension" label="附件格式" min-width="100" align="center"></el-table-column>
      <el-table-column label="操作" min-width="300" fixed="right" align="center">
        <template #default="{ row, $index }">
          <div v-if="row.upStatus">
            <el-tag :type="upStatusTextTypeMap[row.upStatus]">
              <el-icon class="is-loading" v-if="row.upStatus === 'uploading'">
                <Loading />
              </el-icon>{{ upStatusMap[row.upStatus] }}{{ row.upProgress }}
            </el-tag>
          </div>
          <div v-else>
            <el-button link type="primary" icon="Download" :loading="row.downLoading"
              @click="handleDown(row)">下载</el-button>
            <el-button link type="primary" icon="Edit" @click="handleOpenEditDialog(row)">编辑</el-button>
            <el-button link type="primary" icon="View" @click="handlePreview($index)">预览</el-button>
            <el-button link type="danger" icon="Delete" @click="handleDel(row.id)">删除</el-button>
          </div>
        </template>
      </el-table-column>
    </el-table>
  </basic-dialog>
  <!-- 附件编辑，可以同时编辑附件跟属性（密级与用途） -->
  <basic-dialog title="附件编辑" v-model="editVisible" width="800" :autoClose="false" hideFooter>
    <div class="flex_warn">
      <OtherAttr v-if="isAttrShow" v-model="editData" :secretList="secretList"
        :fileDocClassifyList="fileDocClassifyList">
      </OtherAttr>
      <el-upload v-if="editVisible" v-bind="attrs" :drag="drag" :class="{ drag }" :action="action" :headers="{
        ...headers,
        'h-authorization-token': token,
      }" :data="{
        fileDocClassify: editData.fileDocClassify,
        fileDocClassifyName: editData.fileDocClassifyName,
        secret: editData.secret,
        ownId: editData.id,
        ownBus: editData.bus,
        id: editData.id,
        updateFileFlag: true,
        ...data
      }" :show-file-list="false" :limit="1" :multiple="false" :on-exceed="handleEditExceed"
        :on-change="handleEditChange" :on-progress="handleEditProgress">
        <slot>
          <el-button type="primary" icon="upload-filled">附件上传</el-button>
        </slot>
      </el-upload>
    </div>
  </basic-dialog>
  <!-- 只能编辑附件属性 -->
  <basic-dialog v-model="editAttrVisible" title="编辑附件属性" :width="800" :autoClose="false"
    :submitBtnLoading="editAttrSubmitBtnLoading" @submit="handleEditAttrSubmit">
    <div class="flex">
      <OtherAttr v-if="isAttrShow" v-model="otherAttrFormData" :secretList="secretList"
        :fileDocClassifyList="fileDocClassifyList"></OtherAttr>
    </div>
  </basic-dialog>
  <Preview v-model="previewVisible" :needPreviewList="needPreviewList" :belongModule="belongModule"
    :curPreviewIdx="curPreviewIdx"></Preview>
</template>

<script setup>
import { useUserStore } from '@/store/user.js'
import { computed, watch } from 'vue'
import OtherAttr from './OtherAttr.vue'
import Preview from './Preview.vue'
import { cloneDeep } from 'lodash'
import { baseUrl } from '@/env.config.js'
import {
  apiGetList,
  apiGetSecretList,
  apiDel,
  apiDown,
  apiEditOther,
} from '@/apis/file.js'
import { isEmpty } from '@/utils/index.js'
defineOptions({
  inheritAttrs: false,
})
const { token } = storeToRefs(useUserStore())
const action = computed(() => {
  return baseUrl + `/${props.belongModule}/fileController/uploadFile`
})
const attrs = useAttrs()
const props = defineProps({
  btnName: {
    type: String,
    default: '上传附件',
  },
  // 弹窗宽度
  width: {
    type: String,
    default: '1400',
  },
  // 弹窗标题
  title: {
    type: String,
    default: '附件管理',
  },
  // 所属模块
  belongModule: String,
  // 当前行数据
  curRowData: {
    type: Object,
    default: () => ({}),
  },
  // 当前行数据主键，默认为id
  curRowDataKeyField: {
    type: String,
    default: 'id',
  },
  // 用途下拉数据
  fileDocClassifyList: {
    type: Array,
    default: () => [],
  },
  propsHttp: {
    type: Object,
    default: () => ({
      res: 'obj',
      name: 'obj.name',
      url: 'fileViewUrl',
    }),
  },
  // 附带参数
  data: {
    type: Object,
    default: () => ({}),
  },
  // 请求头参数
  headers: {
    type: Object,
    default: () => ({}),
  },
  saveAfter: Function,
  // 上传方式 button 按钮 drag 拖拽
  drag: {
    type: Boolean,
    default: true,
  },
  // 上传附件大小限制 单位kM
  size: {
    type: Number,
    default: 20,
  },
  // 附件上传数量
  limit: {
    type: Number,
    default: 5,
  },
  // 上传之前的操作,返回false则不上传
  beforeUpload: Function,
  // 密级接口的参数
  // 要不不填，要不写huav_must_secret
  busCode: {
    type: String,
    default: '',
  },
  // 是否展示提示
  isTip: {
    type: Boolean,
    default: true,
  },
  // 如果开启提示显示没有设置内容则会根据设置的附件大小和数量自定义提示，如果都没有则直接不展示
  tipText: {
    type: String,
    default: '',
  },
})
const formData = reactive({
  secret: '',
  fileDocClassify: '',
  fileDocClassifyName: '',
})
const visible = ref(false)
// 上传附件状态
// ready 待上传
// uploading 上传中
// success 所有附件上传成功
const upStatusMap = {
  ready: '待上传',
  uploading: '上传中',
  success: '上传成功',
  fail: '上传失败',
}
const upStatusTextTypeMap = {
  ready: 'info',
  uploading: 'primary',
  success: 'success',
  fail: 'danger',
}

// 密级下拉数据
const secretList = ref([])
const fileList = ref([])
const submitBtnLoading = ref(false)
// 当前行数据的主键值
const curRowDataKeyVal = computed(
  () => props.curRowData[props.curRowDataKeyField]
)
// 当前行数据的业务类型
const curRowDataBusVal = computed(() => props.curRowData.bus)

// 是否用途与密级至少有一个展示
const isAttrShow = computed(() => {
  return secretList.value.length > 0 || props.fileDocClassifyList.length > 0
})
// 提示内容
const tipShow = computed(() => {
  // 如果不展示提示则直接返回
  if (!props.isTip) {
    return ''
  }
  // 如果有设置提示内容则直接提示内容
  if (props.tipText) {
    return props.tipText
  }
  // 如果没有设置提示内容则根据设置的附件大小和数量自定义提示
  if (props.size || props.limit) {
    let tip = '上传的附件'
    if (props.size) {
      tip += `大小不能超过${props.size}M，`
    }
    if (props.limit) {
      tip += `附件数量不能超过${props.limit}个，`
    }
    return tip.slice(0, -1)
  } else {
    return ''
  }
})

const handleOpen = () => {
  visible.value = true
}

// 附件上传之前
const handleBeforeUpload = (file) => {
  if (props.size) {
    if (file.size > props.size * 1024 * 1024) {
      ElMessage.warning(`上传附件大小不能超过 ${props.size}M!`)
      return false
    }
  }
  if (fileList.value.length >= props.limit) {
    ElMessage.warning({
      message: `上传附件数量不能超过 ${props.limit}个!`,
      grouping: true,
    })
    exceedUidList.push(file.uid)
    return false
  }
  if (props.beforeUpload && props.beforeUpload(file) === false) {
    return false
  }
  let newFile = fileFormat(file)
  fileList.value.push(newFile)
  return true
}
// 附件上传状态改变
const handlleUpChange = (file, curList) => {
  const { status, uid } = file
  console.log(status, 'statusstatus')
  fileList.value = fileList.value.map((item) => {
    if (item.uid === uid) {
      item.upStatus = status
    }
    return item
  })
  // 准备阶段不让执行是为了有超出附件数量的情况还去刷新页面
  if (file.status === 'ready') {
    return
  }
  checkAllFileUpEnd()
}
const handleProgress = (UploadProgressEvent, file) => {
  fileList.value = fileList.value.map((item) => {
    if (item.uid === file.uid) {
      item.upStatus = 'uploading'
      item.upProgress = UploadProgressEvent.percent.toFixed(2)
    }
    return item
  })
}
// 判断是否所有附件上传结束，上传失败也算结束
const checkAllFileUpEnd = () => {
  if (fileList.value.length === 0) {
    return false
  }
  let flag = fileList.value.some((item) =>
    ['ready', 'uploading'].includes(item.upStatus)
  )
  if (flag) {
    return
  } else {
    getFilelist()
  }
}
// 整理上传之前的附件让他可以再表格的对应属性展示
const fileFormat = (file) => {
  if (file.name.includes('.')) {
    const nameList = file.name.split('.')
    file.showName = nameList[nameList.length - 2]
  } else {
    file.showName = file.name
  }
  file.secret = formData.secret
  file.fileDocClassify = formData.fileDocClassify
  file.fileDocClassifyName = formData.fileDocClassifyName
  file.upStatus = 'ready'
  return file
}

const tableLoading = ref(false)
const selectedlist = ref([])
// 选中切换
const handleSelectChange = (list) => {
  console.log(list, 'list')
  selectedlist.value = list
}
// 获取附件列表
const getFilelist = async () => {
  let resData = await apiGetList(
    props.belongModule,
    {
      ownId: curRowDataKeyVal.value,
      ownBus: curRowDataBusVal.value,
    },
    tableLoading
  )
  fileList.value = resData.map((item) => {
    item.secret = !isEmpty(item.secret) && Number(item.secret)
    return item
  })
}

// 文件下载
const handleDown = (row) => {
  row.downLoading = true
  apiDown(props.belongModule, row.id)
    .then((res) => {
      if (res.length > 0) {
        const url = res[0].url
        window.open(url)
      }
    })
    .finally(() => {
      row.downLoading = false
    })
}

const needPreviewList = ref([])
const previewVisible = ref(false)
const curPreviewIdx = ref(0)
// 附件预览
const handlePreview = (index) => {
  needPreviewList.value = fileList.value.filter((item) => item.id)
  previewVisible.value = true
  curPreviewIdx.value = index
}

// 附件移除
const handleDel = async (id) => {
  let tip = '确认删除该附件吗？'
  if (!id) {
    tip = '确认删除所选附件吗？'
    id = selectedlist.value.map((item) => item.id).join(',')
  }
  ElMessageBox.confirm(tip, '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
    beforeClose: async (action, instance, done) => {
      if (action === 'confirm') {
        instance.confirmButtonLoading = true
        apiDel(props.belongModule, id)
          .then(() => {
            ElMessage.success('删除成功！')
            done()
            getFilelist()
          })
          .finally((res) => {
            instance.confirmButtonLoading = false
          })
      } else {
        done()
      }
    },
  })
}

// 获取密级下拉数据
const getSecretList = async () => {
  const res = await apiGetSecretList(props.busCode || curRowDataBusVal.value)
  secretList.value = res
}

watch(
  () => visible.value,
  (newV) => {
    if (newV) {
      getFilelist()
      getSecretList()
    } else {
      fileList.value = []
    }
  }
)

// 编辑按钮的操作
const useEdit = () => {
  const editVisible = ref(false)
  const editData = ref({})
  let loadInstance = null
  // 打开编辑弹窗
  const handleOpenEditDialog = (row) => {
    editData.value = cloneDeep(row)
    editVisible.value = true
  }

  // 编辑数量超出限制
  const handleEditExceed = () => {
    ElMessage.warning('只能上传一个附件！')
  }

  // 上传进度
  const handleEditProgress = (progress) => {
    loadInstance &&
      loadInstance.setText(
        `文件上传中，当前进度：${progress.percent.toFixed(2)}%`
      )
  }

  // 判断编辑是否成功
  const handleEditChange = (file) => {
    if (file.status === 'success') {
      ElMessage.success('编辑成功！')
      getFilelist()
      editVisible.value = false
      loadInstance && loadInstance.close()
    } else if (file.status === 'ready') {
      loadInstance = ElLoading.service({ text: '文件上传中，当前进度：0%' })
    } else if (file.status === 'fail') {
      ElMessage.error('上传失败，请重试！')
      loadInstance && loadInstance.close()
    }
  }

  return {
    editVisible,
    editData,
    handleEditExceed,
    handleOpenEditDialog,
    handleEditChange,
    handleEditProgress,
  }
}
const {
  editVisible,
  editData,
  handleEditExceed,
  handleOpenEditDialog,
  handleEditChange,
  handleEditProgress,
} = useEdit()

const useEditAttr = () => {
  const editAttrVisible = ref(false)
  const editAttrSubmitBtnLoading = ref(false)
  const otherAttrFormData = reactive({
    secret: '',
    fileDocClassify: '',
    fileDocClassifyName: '',
  })
  //清空选项
  watch(
    () => editAttrVisible.value,
    () => {
      otherAttrFormData.secret = ''
      otherAttrFormData.fileDocClassify = ''
      otherAttrFormData.fileDocClassifyName = ''
    }
  )
  // 打开弹窗
  const handleOpenEditAttrDialog = () => {
    editAttrVisible.value = true
  }
  // 确认
  const handleEditAttrSubmit = () => {
    editAttrSubmitBtnLoading.value = true
    apiEditOther(
      props.belongModule,
      cloneDeep(selectedlist.value).map((item) => {
        item.secret = otherAttrFormData.secret
        item.fileDocClassify = otherAttrFormData.fileDocClassify
        item.fileDocClassifyName = otherAttrFormData.fileDocClassifyName
        return item
      })
    )
      .then(() => {
        ElMessage.success('编辑成功！')
        editAttrVisible.value = false
        getFilelist()
      })
      .finally(() => {
        editAttrSubmitBtnLoading.value = false
      })
  }
  return {
    editAttrVisible,
    otherAttrFormData,
    editAttrSubmitBtnLoading,
    handleOpenEditAttrDialog,
    handleEditAttrSubmit,
  }
}
const {
  editAttrVisible,
  otherAttrFormData,
  editAttrSubmitBtnLoading,
  handleOpenEditAttrDialog,
  handleEditAttrSubmit,
} = useEditAttr()
</script>

<style lang="scss" scoped>
.up_header {
  padding: 10px 0;
  display: flex;
  flex-wrap: wrap;
}

.file_table_table {
  margin-bottom: 6px;
  font-size: 14px;
  font-weight: bold;
}

.drag {
  margin-top: 10px;
  flex-basis: 100%;
}

.tip {
  font-size: 12px;
  color: red;
  font-weight: 400;
}
</style>
